/* menu.cpp - this file is part of PixelMerge
 *
 * Copyright (C) 2010 Pascal Giard
  *
 * Author: Pascal Giard <evilynux@gmail.com>
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This file is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Derived from the libwiigui template by Tantric (2009)
 *
 * Menu logic.
 */

#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <wiiuse/wpad.h>
#include <vector>

#include "libwiigui/gui.h"
#include "menu.h"
#include "pixelmerge.h"
#include "input.h"
#include "filelist.h"
#include "boardview.h"

#define THREAD_SLEEP 100

static GuiImageData * pointer[4];
static GuiImage * bgImg = NULL;
static GuiWindow * subWindow;
static GuiWindow * mainWindow = NULL;
static lwp_t guithread = LWP_THREAD_NULL;
static bool guiHalt = true;
static char appNameAndVersion[20] = "PixelMerge 1.0.1";
static u8 gameDifficulty = HARD;
static bool doneSplash = false;

/****************************************************************************
 * ResumeGui
 *
 * Signals the GUI thread to start, and resumes the thread. This is called
 * after finishing the removal/insertion of new elements, and after initial
 * GUI setup.
 ***************************************************************************/
void ResumeGui() {
  guiHalt = false;
  LWP_ResumeThread (guithread);
}

/****************************************************************************
 * HaltGui
 *
 * Signals the GUI thread to stop, and waits for GUI thread to stop
 * This is necessary whenever removing/inserting new elements into the GUI.
 * This eliminates the possibility that the GUI is in the middle of accessing
 * an element that is being changed.
 ***************************************************************************/
void HaltGui() {
  guiHalt = true;

  // wait for thread to finish
  while(!LWP_ThreadIsSuspended(guithread))
    usleep(THREAD_SLEEP);
}

/****************************************************************************
 * WindowPrompt
 *
 * Displays a prompt window to user, with information, an error message, or
 * presenting a user with a choice
 ***************************************************************************/
int WindowPrompt(const char *title, const char *msg,
                 const char *btn1Label, const char *btn2Label)
{
  int choice = -1;

  GuiWindow promptWindow(448,288);
  promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  promptWindow.SetPosition(0, -10);
  GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
  GuiImageData btnOutline(button_png);
  GuiImageData btnOutlineOver(button_over_png);
  GuiTrigger trigA;
  trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A,
                         PAD_BUTTON_A);

  GuiImageData dialogBox(dialogue_box_png);
  GuiImage dialogBoxImg(&dialogBox);

  GuiText titleTxt(title, 26, (GXColor){0, 0, 0, DEF_ALPHA});
  titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
  titleTxt.SetPosition(0,40);
  GuiText msgTxt(msg, 22, (GXColor){0, 0, 0, DEF_ALPHA});
  msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  msgTxt.SetPosition(0,-20);
  msgTxt.SetWrap(true, 400);

  GuiText btn1Txt(btn1Label, 22, (GXColor){255, 255, 255, 255});
  GuiImage btn1Img(&btnOutline);
  GuiImage btn1ImgOver(&btnOutlineOver);
  GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight());

  if(btn2Label) {
    btn1.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
    btn1.SetPosition(20, -25);
  } else {
    btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
    btn1.SetPosition(0, -25);
  }

  btn1.SetLabel(&btn1Txt);
  btn1.SetImage(&btn1Img);
  btn1.SetImageOver(&btn1ImgOver);
  btn1.SetSoundOver(&btnSoundOver);
  btn1.SetTrigger(&trigA);
  btn1.SetState(STATE_SELECTED);
  btn1.SetEffectGrow();

  GuiText btn2Txt(btn2Label, 22, (GXColor){255, 255, 255, 255});
  GuiImage btn2Img(&btnOutline);
  GuiImage btn2ImgOver(&btnOutlineOver);
  GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight());
  btn2.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM);
  btn2.SetPosition(-20, -25);
  btn2.SetLabel(&btn2Txt);
  btn2.SetImage(&btn2Img);
  btn2.SetImageOver(&btn2ImgOver);
  btn2.SetSoundOver(&btnSoundOver);
  btn2.SetTrigger(&trigA);
  btn2.SetEffectGrow();

  promptWindow.Append(&dialogBoxImg);
  promptWindow.Append(&titleTxt);
  promptWindow.Append(&msgTxt);
  promptWindow.Append(&btn1);

  if(btn2Label)
    promptWindow.Append(&btn2);

  promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50);
  HaltGui();
  mainWindow->SetState(STATE_DISABLED);
  mainWindow->Append(&promptWindow);
  mainWindow->ChangeFocus(&promptWindow);
  ResumeGui();

  while(choice == -1) {
    usleep(THREAD_SLEEP);
    
    if(btn1.GetState() == STATE_CLICKED)
      choice = 1;
    else if(btn2.GetState() == STATE_CLICKED)
      choice = 0;
  }

  promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50);
  while(promptWindow.GetEffect() > 0) usleep(THREAD_SLEEP);
  HaltGui();
  mainWindow->Remove(&promptWindow);
  mainWindow->SetState(STATE_DEFAULT);
  ResumeGui();
  return choice;
}

/****************************************************************************
 * SplashScreen
 *
 * Displays splash screen of the Nintendomax Wii Dev Competition 2010.
 ***************************************************************************/
void SplashScreen() {
  doneSplash = false;
  GuiWindow splash(640, 480);
  splash.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  splash.SetPosition(0, 0);
  splash.SetEffect(EFFECT_FADE, 5);
  GuiImageData splashImgData(devcompo_splash_png);
  GuiImage splashImg(&splashImgData);

  HaltGui();
  splash.Append(&splashImg);
  ResumeGui();

  HaltGui();
  mainWindow->SetState(STATE_DISABLED);
  mainWindow->Append(&splash);
  mainWindow->ChangeFocus(&splash);
  ResumeGui();

  while(splash.GetEffect() > 0) usleep(100);
  usleep(5000000);
  splash.SetEffect(EFFECT_FADE, -5);
  while(splash.GetEffect() > 0) usleep(100);
  HaltGui();
  mainWindow->Remove(&splash);
  mainWindow->SetState(STATE_DEFAULT);
  ResumeGui();
  doneSplash = true;
  
  return;
}

/****************************************************************************
 * AboutBox
 *
 * Displays information about the game.
 ***************************************************************************/
void AboutBox() {
  GuiWindow promptWindow(448,288);
  promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  promptWindow.SetPosition(0, -10);
  GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
  GuiImageData btnOutline(button_png);
  GuiImageData btnOutlineOver(button_over_png);
  GuiTrigger trigA;
  trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A,
                         PAD_BUTTON_A);

  GuiImageData dialogBox(dialogue_box_png);
  GuiImage dialogBoxImg(&dialogBox);

  GuiText titleTxt(appNameAndVersion, 26, (GXColor){0, 0, 0, DEF_ALPHA});
  titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
  titleTxt.SetPosition(0,40);

  GuiText msg1Txt(_("Free/libre Flood-It clone released under the GNU GPL."),
                  22, (GXColor){0, 0, 0, DEF_ALPHA});
  msg1Txt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  msg1Txt.SetPosition(0,-20);
  msg1Txt.SetWrap(true, 400);

  GuiText msg2Txt("Copyright 2010 Pascal Giard",
                  22, (GXColor){0, 0, 0, DEF_ALPHA});
  msg2Txt.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  msg2Txt.SetPosition(0,-100);

  GuiText btnTxt(_("Close"), 22, (GXColor){255, 255, 255, 255});
  GuiImage btnImg(&btnOutline);
  GuiImage btnImgOver(&btnOutlineOver);
  GuiButton btn(btnOutline.GetWidth(), btnOutline.GetHeight());

  btn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  btn.SetPosition(0, -25);
  btn.SetLabel(&btnTxt);
  btn.SetImage(&btnImg);
  btn.SetImageOver(&btnImgOver);
  btn.SetSoundOver(&btnSoundOver);
  btn.SetTrigger(&trigA);
  btn.SetState(STATE_SELECTED);
  btn.SetEffectGrow();

  promptWindow.Append(&dialogBoxImg);
  promptWindow.Append(&titleTxt);
  promptWindow.Append(&msg1Txt);
  promptWindow.Append(&msg2Txt);
  promptWindow.Append(&btn);

  promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50);
  HaltGui();
  mainWindow->SetState(STATE_DISABLED);
  mainWindow->Append(&promptWindow);
  mainWindow->ChangeFocus(&promptWindow);
  ResumeGui();

  while(btn.GetState() != STATE_CLICKED) {
    usleep(THREAD_SLEEP);
  }

  promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50);
  while(promptWindow.GetEffect() > 0) usleep(THREAD_SLEEP);
  HaltGui();
  mainWindow->Remove(&promptWindow);
  mainWindow->SetState(STATE_DEFAULT);
  ResumeGui();
}

/****************************************************************************
 * UpdateGUI
 *
 * Primary thread to allow GUI to respond to state changes, and draws GUI
 ***************************************************************************/
static void * UpdateGUI (void *arg) {
  int i;

  while(1) {
    if(guiHalt) {
      LWP_SuspendThread(guithread);
    } else {
      UpdatePads();
      mainWindow->Draw();

#ifdef HW_RVL
      for(i=3; i >= 0; i--) { // so that player 1's cursor appears on top!
        if(userInput[i].wpad->ir.valid && doneSplash)
          Menu_DrawImg(userInput[i].wpad->ir.x-48,
                       userInput[i].wpad->ir.y-48,
                       96, 96, pointer[i]->GetImage(),
                       userInput[i].wpad->ir.angle, 1, 1, 255);
        DoRumble(i);
      }
#endif

      Menu_Render();

      for(i=0; i < 4; i++)
        mainWindow->Update(&userInput[i]);

      if(ExitRequested) {
        for(i = 0; i < 255; i += 15) {
          mainWindow->Draw();
          Menu_DrawRectangle(0, 0, screenwidth, screenheight,
                             (GXColor){0, 0, 0, i}, 1);
          Menu_Render();
        }
        ExitApp();
      }
    }
  }
  return NULL;
}

/****************************************************************************
 * InitGUIThread
 *
 * Startup GUI threads
 ***************************************************************************/
void InitGUIThreads() {
  LWP_CreateThread (&guithread, UpdateGUI, NULL, NULL, 0, 70);
}

/****************************************************************************
 * MenuStart - Main Window
 ***************************************************************************/
static int MenuStart() {
  int menu = MENU_NONE;

  subWindow = new GuiWindow(screenwidth, screenheight);

  GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
  GuiImageData btnOutline(button_png);
  GuiImageData btnOutlineOver(button_over_png);

  GuiImageData logoImgData(logo_png);
  GuiImage logoImg(&logoImgData);
  logoImg.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
  logoImg.SetPosition((screenwidth-logoImgData.GetWidth())>>1, screenheight>>2);
  
  GuiTrigger trigA;
  trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A,
                         PAD_BUTTON_A);
  GuiTrigger trigHome;
  trigHome.SetButtonOnlyTrigger(-1, 
                                WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);

  GuiText exitBtnTxt(_("Exit"), 22, (GXColor){255, 255, 255, 255});
  GuiImage exitBtnImg(&btnOutline);
  GuiImage exitBtnImgOver(&btnOutlineOver);
  GuiButton exitBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  exitBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  exitBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1, -20);
  exitBtn.SetLabel(&exitBtnTxt);
  exitBtn.SetImage(&exitBtnImg);
  exitBtn.SetImageOver(&exitBtnImgOver);
  exitBtn.SetSoundOver(&btnSoundOver);
  exitBtn.SetTrigger(&trigA);
  exitBtn.SetTrigger(&trigHome);
  exitBtn.SetEffectGrow();

  GuiText playBtnTxt(_("Play"), 22, (GXColor){255, 255, 255, 255});
  GuiImage playBtnImg(&btnOutline);
  GuiImage playBtnImgOver(&btnOutlineOver);
  GuiButton playBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  playBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  playBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1,
                      -30-3*btnOutline.GetHeight());
  playBtn.SetLabel(&playBtnTxt);
  playBtn.SetImage(&playBtnImg);
  playBtn.SetImageOver(&playBtnImgOver);
  playBtn.SetSoundOver(&btnSoundOver);
  playBtn.SetTrigger(&trigA);
  playBtn.SetEffectGrow();

  GuiText settingsBtnTxt(_("Settings"), 22, (GXColor){255, 255, 255, 255});
  GuiImage settingsBtnImg(&btnOutline);
  GuiImage settingsBtnImgOver(&btnOutlineOver);
  GuiButton settingsBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  settingsBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  settingsBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1,
                          -30-2*btnOutline.GetHeight());
  settingsBtn.SetLabel(&settingsBtnTxt);
  settingsBtn.SetImage(&settingsBtnImg);
  settingsBtn.SetImageOver(&settingsBtnImgOver);
  settingsBtn.SetSoundOver(&btnSoundOver);
  settingsBtn.SetTrigger(&trigA);
  settingsBtn.SetEffectGrow();

  GuiText aboutBtnTxt(_("About"), 22, (GXColor){255, 255, 255, 255});
  GuiImage aboutBtnImg(&btnOutline);
  GuiImage aboutBtnImgOver(&btnOutlineOver);
  GuiButton aboutBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  aboutBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  aboutBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1,
                       -30-btnOutline.GetHeight());
  aboutBtn.SetLabel(&aboutBtnTxt);
  aboutBtn.SetImage(&aboutBtnImg);
  aboutBtn.SetImageOver(&aboutBtnImgOver);
  aboutBtn.SetSoundOver(&btnSoundOver);
  aboutBtn.SetTrigger(&trigA);
  aboutBtn.SetEffectGrow();

  HaltGui();

  subWindow->Append(&logoImg);
  subWindow->Append(&exitBtn);
  subWindow->Append(&playBtn);
  subWindow->Append(&settingsBtn);
  subWindow->Append(&aboutBtn);

  mainWindow->Append(subWindow);

  ResumeGui();

  while(menu == MENU_NONE) {
    usleep(THREAD_SLEEP);

    if(exitBtn.GetState() == STATE_CLICKED) {
      menu = MENU_EXIT;
    } else if(playBtn.GetState() == STATE_CLICKED) {
      menu = MENU_DIFF;
    } else if(settingsBtn.GetState() == STATE_CLICKED) {
      menu = MENU_SETTINGS;
    } else if(aboutBtn.GetState() == STATE_CLICKED) {
      AboutBox();
    }
  }

  HaltGui();
  mainWindow->Remove(subWindow);
  delete subWindow;

  return menu;
}

/****************************************************************************
 * MenuDiff - Choose game difficulty
 ***************************************************************************/
static int MenuDiff() {
  int menu = MENU_NONE;

  subWindow = new GuiWindow(screenwidth, screenheight);

  GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
  GuiImageData btnOutline(button_png);
  GuiImageData btnOutlineOver(button_over_png);

  GuiImageData logoImgData(logo_png);
  GuiImage logoImg(&logoImgData);
  logoImg.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
  logoImg.SetPosition((screenwidth-logoImgData.GetWidth())>>1, screenheight>>2);
  

  GuiTrigger trigA;
  trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A,
                         PAD_BUTTON_A);
  GuiTrigger trigHome;
  trigHome.SetButtonOnlyTrigger(-1, 
                                WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);

  GuiText exitBtnTxt(_("Back"), 22, (GXColor){255, 255, 255, 255});
  GuiImage exitBtnImg(&btnOutline);
  GuiImage exitBtnImgOver(&btnOutlineOver);
  GuiButton exitBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  exitBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  exitBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1, -20);
  exitBtn.SetLabel(&exitBtnTxt);
  exitBtn.SetImage(&exitBtnImg);
  exitBtn.SetImageOver(&exitBtnImgOver);
  exitBtn.SetSoundOver(&btnSoundOver);
  exitBtn.SetTrigger(&trigA);
  exitBtn.SetTrigger(&trigHome);
  exitBtn.SetEffectGrow();

  GuiText easyBtnTxt(_("Easy"), 22, (GXColor){255, 255, 255, 255});
  GuiImage easyBtnImg(&btnOutline);
  GuiImage easyBtnImgOver(&btnOutlineOver);
  GuiButton easyBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  easyBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  easyBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1,
                      -30-3*btnOutline.GetHeight());
  easyBtn.SetLabel(&easyBtnTxt);
  easyBtn.SetImage(&easyBtnImg);
  easyBtn.SetImageOver(&easyBtnImgOver);
  easyBtn.SetSoundOver(&btnSoundOver);
  easyBtn.SetTrigger(&trigA);
  easyBtn.SetEffectGrow();

  GuiText normalBtnTxt(_("Normal"), 22, (GXColor){255, 255, 255, 255});
  GuiImage normalBtnImg(&btnOutline);
  GuiImage normalBtnImgOver(&btnOutlineOver);
  GuiButton normalBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  normalBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  normalBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1,
                        -30-2*btnOutline.GetHeight());
  normalBtn.SetLabel(&normalBtnTxt);
  normalBtn.SetImage(&normalBtnImg);
  normalBtn.SetImageOver(&normalBtnImgOver);
  normalBtn.SetSoundOver(&btnSoundOver);
  normalBtn.SetTrigger(&trigA);
  normalBtn.SetEffectGrow();

  GuiText hardBtnTxt(_("Hard"), 22, (GXColor){255, 255, 255, 255});
  GuiImage hardBtnImg(&btnOutline);
  GuiImage hardBtnImgOver(&btnOutlineOver);
  GuiButton hardBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  hardBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  hardBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1,
                      -30-btnOutline.GetHeight());
  hardBtn.SetLabel(&hardBtnTxt);
  hardBtn.SetImage(&hardBtnImg);
  hardBtn.SetImageOver(&hardBtnImgOver);
  hardBtn.SetSoundOver(&btnSoundOver);
  hardBtn.SetTrigger(&trigA);
  hardBtn.SetEffectGrow();

  HaltGui();

  subWindow->Append(&logoImg);
  subWindow->Append(&exitBtn);
  subWindow->Append(&easyBtn);
  subWindow->Append(&normalBtn);
  subWindow->Append(&hardBtn);

  mainWindow->Append(subWindow);

  ResumeGui();

  while(menu == MENU_NONE) {
    usleep(THREAD_SLEEP);

    if(exitBtn.GetState() == STATE_CLICKED) {
      menu = MENU_START;
    } else if(easyBtn.GetState() == STATE_CLICKED) {
      gameDifficulty = EASY;
      menu = MENU_GAME;
    } else if(normalBtn.GetState() == STATE_CLICKED) {
      gameDifficulty = NORMAL;
      menu = MENU_GAME;
    } else if(hardBtn.GetState() == STATE_CLICKED) {
      gameDifficulty = HARD;
      menu = MENU_GAME;
    }
  }

  HaltGui();
  mainWindow->Remove(subWindow);
  delete subWindow;

  return menu;
}

/****************************************************************************
 * MenuSettings - Reset records, set autosave record, set language or 
 *                go to adjust screen.
 ***************************************************************************/
static int MenuSettings() {
  int menu = MENU_NONE;

  subWindow = new GuiWindow(screenwidth, screenheight);

  GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
  GuiImageData btnOutline(button_png);
  GuiImageData btnOutlineOver(button_over_png);
  GuiImageData arrowImgData(arrow_top_png);
  GuiImageData arrowOverImgData(arrow_top_over_png);

  GuiText settingsTxt(_("Settings"), 36, (GXColor){255, 255, 255, 255});
  settingsTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
  settingsTxt.SetPosition(0, screenheight>>2);
  
  GuiTrigger trigA;
  trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A,
                         PAD_BUTTON_A);
  GuiTrigger trigHome;
  trigHome.SetButtonOnlyTrigger(-1, 
                                WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);

  GuiText exitBtnTxt(_("Back"), 22, (GXColor){255, 255, 255, 255});
  GuiImage exitBtnImg(&btnOutline);
  GuiImage exitBtnImgOver(&btnOutlineOver);
  GuiButton exitBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  exitBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  exitBtn.SetPosition((screenwidth-btnOutline.GetWidth())>>1, -20);
  exitBtn.SetLabel(&exitBtnTxt);
  exitBtn.SetImage(&exitBtnImg);
  exitBtn.SetImageOver(&exitBtnImgOver);
  exitBtn.SetSoundOver(&btnSoundOver);
  exitBtn.SetTrigger(&trigA);
  exitBtn.SetTrigger(&trigHome);
  exitBtn.SetEffectGrow();

  GuiText langTxt(_("Language"), 26, (GXColor){255, 255, 255, 255});
  langTxt.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  langTxt.SetPosition(screenwidth>>3, -40-4*btnOutline.GetHeight());
  GuiText langValTxt(pxlMgSettings->getLanguage(),
                     24, (GXColor){255, 255, 255, 255});
  langValTxt.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  langValTxt.SetPosition(screenwidth>>2,
                         -40-4*btnOutline.GetHeight());
  // Left
  GuiImage langLeft(&arrowImgData);
  langLeft.SetAngle(-90.0);
  GuiImage langLeftOver(&arrowOverImgData);
  langLeftOver.SetAngle(-90.0);
  GuiButton langLeftBtn(langLeft.GetWidth(),
                        langLeft.GetHeight());
  langLeftBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  langLeftBtn.SetPosition((screenwidth>>2)-80,
                          -35-4*btnOutline.GetHeight());
  langLeftBtn.SetImage(&langLeft);
  langLeftBtn.SetImageOver(&langLeftOver);
  langLeftBtn.SetSoundOver(&btnSoundOver);
  langLeftBtn.SetTrigger(&trigA);
  langLeftBtn.SetEffectGrow();
  // Right
  GuiImage langRight(&arrowImgData);
  langRight.SetAngle(90.0);
  GuiImage langRightOver(&arrowOverImgData);
  langRightOver.SetAngle(90.0);
  GuiButton langRightBtn(langRight.GetWidth(),
                         langRight.GetHeight());
  langRightBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  langRightBtn.SetPosition((screenwidth>>2)+80,
                           -35-4*btnOutline.GetHeight());
  langRightBtn.SetImage(&langRight);
  langRightBtn.SetImageOver(&langRightOver);
  langRightBtn.SetSoundOver(&btnSoundOver);
  langRightBtn.SetTrigger(&trigA);
  langRightBtn.SetEffectGrow();

  GuiText autoSaveTxt(_("Autosave records"), 26,
                      (GXColor){255, 255, 255, 255});
  autoSaveTxt.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
  autoSaveTxt.SetPosition(screenwidth>>3, -40-3*btnOutline.GetHeight());
  GuiText autoSaveValTxt(pxlMgSettings->user.autoSave ? _("On") : _("Off"),
                         24, (GXColor){255, 255, 255, 255});
  autoSaveValTxt.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  autoSaveValTxt.SetPosition(screenwidth>>2,
                             -40-3*btnOutline.GetHeight());
  // Left
  GuiImage autoSaveLeft(&arrowImgData);
  autoSaveLeft.SetAngle(-90.0);
  GuiImage autoSaveLeftOver(&arrowOverImgData);
  autoSaveLeftOver.SetAngle(-90.0);
  GuiButton autoSaveLeftBtn(autoSaveLeft.GetWidth(),
                            autoSaveLeft.GetHeight());
  autoSaveLeftBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  autoSaveLeftBtn.SetPosition((screenwidth>>2)-50,
                              -35-3*btnOutline.GetHeight());
  autoSaveLeftBtn.SetImage(&autoSaveLeft);
  autoSaveLeftBtn.SetImageOver(&autoSaveLeftOver);
  autoSaveLeftBtn.SetSoundOver(&btnSoundOver);
  autoSaveLeftBtn.SetTrigger(&trigA);
  autoSaveLeftBtn.SetEffectGrow();
  // Right
  GuiImage autoSaveRight(&arrowImgData);
  autoSaveRight.SetAngle(90.0);
  GuiImage autoSaveRightOver(&arrowOverImgData);
  autoSaveRightOver.SetAngle(90.0);
  GuiButton autoSaveRightBtn(autoSaveRight.GetWidth(),
                             autoSaveRight.GetHeight());
  autoSaveRightBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  autoSaveRightBtn.SetPosition((screenwidth>>2)+50,
                              -35-3*btnOutline.GetHeight());
  autoSaveRightBtn.SetImage(&autoSaveRight);
  autoSaveRightBtn.SetImageOver(&autoSaveRightOver);
  autoSaveRightBtn.SetSoundOver(&btnSoundOver);
  autoSaveRightBtn.SetTrigger(&trigA);
  autoSaveRightBtn.SetEffectGrow();

  GuiText rstRecordsTxt(_("Reset Records"), 22, (GXColor){255, 255, 255, 255});
  GuiImage rstRecordsBtnImg(&btnOutline);
  GuiImage rstRecordsBtnImgOver(&btnOutlineOver);
  GuiButton rstRecordsBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  rstRecordsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  rstRecordsBtn.SetPosition(0, -30-2*btnOutline.GetHeight());
  rstRecordsBtn.SetLabel(&rstRecordsTxt);
  rstRecordsBtn.SetImage(&rstRecordsBtnImg);
  rstRecordsBtn.SetImageOver(&rstRecordsBtnImgOver);
  rstRecordsBtn.SetSoundOver(&btnSoundOver);
  rstRecordsBtn.SetTrigger(&trigA);
  rstRecordsBtn.SetTrigger(&trigHome);
  rstRecordsBtn.SetEffectGrow();

  GuiText adjScreenTxt(_("Adjust Screen"), 22, (GXColor){255, 255, 255, 255});
  GuiImage adjScreenBtnImg(&btnOutline);
  GuiImage adjScreenBtnImgOver(&btnOutlineOver);
  GuiButton adjScreenBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  adjScreenBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  adjScreenBtn.SetPosition(0, -30-btnOutline.GetHeight());
  adjScreenBtn.SetLabel(&adjScreenTxt);
  adjScreenBtn.SetImage(&adjScreenBtnImg);
  adjScreenBtn.SetImageOver(&adjScreenBtnImgOver);
  adjScreenBtn.SetSoundOver(&btnSoundOver);
  adjScreenBtn.SetTrigger(&trigA);
  adjScreenBtn.SetTrigger(&trigHome);
  adjScreenBtn.SetEffectGrow();

  HaltGui();

  subWindow->Append(&settingsTxt);
  subWindow->Append(&exitBtn);
  subWindow->Append(&langTxt);
  subWindow->Append(&langValTxt);
  subWindow->Append(&langLeftBtn);
  subWindow->Append(&langRightBtn);
  subWindow->Append(&autoSaveTxt);
  subWindow->Append(&autoSaveValTxt);
  subWindow->Append(&autoSaveLeftBtn);
  subWindow->Append(&autoSaveRightBtn);
  subWindow->Append(&rstRecordsBtn);
  subWindow->Append(&adjScreenBtn);

  mainWindow->Append(subWindow);

  ResumeGui();

  while(menu == MENU_NONE) {
    usleep(THREAD_SLEEP);

    if(exitBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->save();
      menu = MENU_START;
    } else if(langLeftBtn.GetState() == STATE_CLICKED) {
      langValTxt.SetText(pxlMgSettings->getPreviousValidLanguage());
      pxlMgSettings->reloadLanguage();
      menu = MENU_SETTINGS;
    } else if(langRightBtn.GetState() == STATE_CLICKED) {
      langValTxt.SetText(pxlMgSettings->getNextValidLanguage());
      pxlMgSettings->reloadLanguage();
      menu = MENU_SETTINGS;
    } else if(autoSaveLeftBtn.GetState() == STATE_CLICKED ||
              autoSaveRightBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->user.autoSave = !pxlMgSettings->user.autoSave;
      autoSaveValTxt.SetText(pxlMgSettings->user.autoSave ?
                             _("On") : _("Off"));
      HaltGui();
      autoSaveLeftBtn.SetState(STATE_DEFAULT, -1);
      autoSaveRightBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
    } else if(rstRecordsBtn.GetState() == STATE_CLICKED) {
      int choice =
        WindowPrompt(_("Records Deletion"),
                     _("Permanently delete records for all difficulties?"),
                     _("Yes"),
                     _("Cancel"));
      if(choice) {
        pxlMgSettings->resetRecords();
      }
      HaltGui();
      rstRecordsBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
    } else if(adjScreenBtn.GetState() == STATE_CLICKED) {
      menu = MENU_ADJUST_SCREEN;
    }
  }

  HaltGui();
  mainWindow->Remove(subWindow);
  delete subWindow;

  return menu;
}

/****************************************************************************
 * MenuSettings - Graphical screen adjustment
 ***************************************************************************/
static int MenuAdjustScreen() {
  int menu = MENU_NONE;
  VideoSettings oldVideo = pxlMgSettings->video;

  subWindow = new GuiWindow(screenwidth, screenheight);

  GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
  GuiImageData btnOutline(button_png);
  GuiImageData btnOutlineOver(button_over_png);

  GuiImageData bgImgData(bg_screen_settings_png);
  GuiImage bgImg(&bgImgData);
  bgImg.SetPosition(0,0);
  
  GuiTrigger trigA;
  trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A,
                         PAD_BUTTON_A);

  GuiTrigger trigHome;
  trigHome.SetButtonOnlyTrigger(-1, 
                                WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0);

  GuiText positionTxt(_("Position"), 30, (GXColor){255, 255, 255, 255});
  positionTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  positionTxt.SetPosition(-100, -80);

  char posValue[8];
  snprintf(posValue, sizeof(posValue), "%i,%i", 
           pxlMgSettings->video.offsetX, pxlMgSettings->video.offsetY);
  GuiText posValueTxt(posValue, 22, (GXColor){255, 255, 255, 255});
  posValueTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  posValueTxt.SetPosition(-100, 0);

  char scaleValue[12];
  snprintf(scaleValue, sizeof(scaleValue), "%i%%,%i%%", 
           pxlMgSettings->video.scaleX, pxlMgSettings->video.scaleY);
  GuiText scaleValueTxt(scaleValue, 22, (GXColor){255, 255, 255, 255});
  scaleValueTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  scaleValueTxt.SetPosition(100, 0);

  GuiImageData arrowImgData(arrow_top_png);
  GuiImageData arrowOverImgData(arrow_top_over_png);
  GuiImageData plusImgData(plus_png);
  GuiImageData plusOverImgData(plus_over_png);
  GuiImageData minusImgData(minus_png);
  GuiImageData minusOverImgData(minus_over_png);
  // Top
  GuiImage arrowTop(&arrowImgData);
  GuiImage arrowTopOver(&arrowOverImgData);
  GuiImage minusTop(&minusImgData);
  GuiImage minusTopOver(&minusOverImgData);
  // Bottom
  GuiImage arrowBottom(&arrowImgData);
  arrowBottom.SetAngle(180.0);
  GuiImage arrowBottomOver(&arrowOverImgData);
  arrowBottomOver.SetAngle(180.0);
  GuiImage plusBottom(&plusImgData);
  GuiImage plusBottomOver(&plusOverImgData);
  // Left
  GuiImage arrowLeft(&arrowImgData);
  arrowLeft.SetAngle(-90.0);
  GuiImage arrowLeftOver(&arrowOverImgData);
  arrowLeftOver.SetAngle(-90.0);
  GuiImage minusLeft(&minusImgData);
  GuiImage minusLeftOver(&minusOverImgData);
  // Right
  GuiImage arrowRight(&arrowImgData);
  arrowRight.SetAngle(90.0);
  GuiImage arrowRightOver(&arrowOverImgData);
  arrowRightOver.SetAngle(90.0);
  GuiImage plusRight(&plusImgData);
  GuiImage plusRightOver(&plusOverImgData);

  GuiButton posTopBtn(arrowTop.GetWidth(), arrowTop.GetHeight());
  posTopBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  posTopBtn.SetPosition(-100, -40);
  posTopBtn.SetImage(&arrowTop);
  posTopBtn.SetImageOver(&arrowTopOver);
  posTopBtn.SetSoundOver(&btnSoundOver);
  posTopBtn.SetTrigger(&trigA);
  posTopBtn.SetEffectGrow();

  GuiButton posBottomBtn(arrowBottom.GetWidth(), arrowBottom.GetHeight());
  posBottomBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  posBottomBtn.SetPosition(-100, 40);
  posBottomBtn.SetImage(&arrowBottom);
  posBottomBtn.SetImageOver(&arrowBottomOver);
  posBottomBtn.SetSoundOver(&btnSoundOver);
  posBottomBtn.SetTrigger(&trigA);
  posBottomBtn.SetEffectGrow();

  GuiButton posLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight());
  posLeftBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  posLeftBtn.SetPosition(-160, 0);
  posLeftBtn.SetImage(&arrowLeft);
  posLeftBtn.SetImageOver(&arrowLeftOver);
  posLeftBtn.SetSoundOver(&btnSoundOver);
  posLeftBtn.SetTrigger(&trigA);
  posLeftBtn.SetEffectGrow();

  GuiButton posRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight());
  posRightBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  posRightBtn.SetPosition(-40, 0);
  posRightBtn.SetImage(&arrowRight);
  posRightBtn.SetImageOver(&arrowRightOver);
  posRightBtn.SetSoundOver(&btnSoundOver);
  posRightBtn.SetTrigger(&trigA);
  posRightBtn.SetEffectGrow();

  GuiText scaleTxt(_("Scale"), 30, (GXColor){255, 255, 255, 255});
  scaleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  scaleTxt.SetPosition(100, -80);

  GuiButton scaleTopBtn(minusTop.GetWidth(), minusTop.GetHeight());
  scaleTopBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  scaleTopBtn.SetPosition(100, -40);
  scaleTopBtn.SetImage(&minusTop);
  scaleTopBtn.SetImageOver(&minusTopOver);
  scaleTopBtn.SetSoundOver(&btnSoundOver);
  scaleTopBtn.SetTrigger(&trigA);
  scaleTopBtn.SetEffectGrow();

  GuiButton scaleBottomBtn(plusBottom.GetWidth(), plusBottom.GetHeight());
  scaleBottomBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  scaleBottomBtn.SetPosition(100, 40);
  scaleBottomBtn.SetImage(&plusBottom);
  scaleBottomBtn.SetImageOver(&plusBottomOver);
  scaleBottomBtn.SetSoundOver(&btnSoundOver);
  scaleBottomBtn.SetTrigger(&trigA);
  scaleBottomBtn.SetEffectGrow();

  GuiButton scaleLeftBtn(minusLeft.GetWidth(), minusLeft.GetHeight());
  scaleLeftBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  scaleLeftBtn.SetPosition(30, 0);
  scaleLeftBtn.SetImage(&minusLeft);
  scaleLeftBtn.SetImageOver(&minusLeftOver);
  scaleLeftBtn.SetSoundOver(&btnSoundOver);
  scaleLeftBtn.SetTrigger(&trigA);
  scaleLeftBtn.SetEffectGrow();

  GuiButton scaleRightBtn(plusRight.GetWidth(), plusRight.GetHeight());
  scaleRightBtn.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
  scaleRightBtn.SetPosition(170, 0);
  scaleRightBtn.SetImage(&plusRight);
  scaleRightBtn.SetImageOver(&plusRightOver);
  scaleRightBtn.SetSoundOver(&btnSoundOver);
  scaleRightBtn.SetTrigger(&trigA);
  scaleRightBtn.SetEffectGrow();

  GuiText saveBtnTxt(_("Save"), 22, (GXColor){255, 255, 255, 255});
  GuiImage saveBtnImg(&btnOutline);
  GuiImage saveBtnImgOver(&btnOutlineOver);
  GuiButton saveBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  saveBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  saveBtn.SetPosition(-btnOutline.GetWidth()>>1, -40);
  saveBtn.SetLabel(&saveBtnTxt);
  saveBtn.SetImage(&saveBtnImg);
  saveBtn.SetImageOver(&saveBtnImgOver);
  saveBtn.SetSoundOver(&btnSoundOver);
  saveBtn.SetTrigger(&trigA);
  saveBtn.SetEffectGrow();

  GuiText cancelBtnTxt(_("Cancel"), 22, (GXColor){255, 255, 255, 255});
  GuiImage cancelBtnImg(&btnOutline);
  GuiImage cancelBtnImgOver(&btnOutlineOver);
  GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
  cancelBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
  cancelBtn.SetPosition(btnOutline.GetWidth()>>1, -40);
  cancelBtn.SetLabel(&cancelBtnTxt);
  cancelBtn.SetImage(&cancelBtnImg);
  cancelBtn.SetImageOver(&cancelBtnImgOver);
  cancelBtn.SetSoundOver(&btnSoundOver);
  cancelBtn.SetTrigger(&trigA);
  cancelBtn.SetTrigger(&trigHome);
  cancelBtn.SetEffectGrow();

  HaltGui();

  subWindow->Append(&bgImg);
  subWindow->Append(&saveBtn);
  subWindow->Append(&cancelBtn);
  subWindow->Append(&positionTxt);
  subWindow->Append(&posValueTxt);
  subWindow->Append(&posTopBtn);
  subWindow->Append(&posBottomBtn);
  subWindow->Append(&posLeftBtn);
  subWindow->Append(&posRightBtn);
  subWindow->Append(&scaleTxt);
  subWindow->Append(&scaleValueTxt);
  subWindow->Append(&scaleTopBtn);
  subWindow->Append(&scaleBottomBtn);
  subWindow->Append(&scaleLeftBtn);
  subWindow->Append(&scaleRightBtn);

  mainWindow->Append(subWindow);

  ResumeGui();
  int updateVideo = 0;

  while(menu == MENU_NONE) {
    usleep(THREAD_SLEEP);
    if(cancelBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video = oldVideo;
      updateVideo = 1;
      menu = MENU_SETTINGS;
    } else if(saveBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->save();
      menu = MENU_SETTINGS;
    } else if(posTopBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.offsetY--;
      HaltGui();
      posTopBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    } else if(posBottomBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.offsetY++;
      HaltGui();
      posBottomBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    } else if(posLeftBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.offsetX--;
      HaltGui();
      posLeftBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    } else if(posRightBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.offsetX++;
      HaltGui();
      posRightBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    } else if(scaleTopBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.scaleY--;
      HaltGui();
      scaleTopBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    } else if(scaleBottomBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.scaleY++;
      HaltGui();
      scaleBottomBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    } else if(scaleLeftBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.scaleX--;
      HaltGui();
      scaleLeftBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    } else if(scaleRightBtn.GetState() == STATE_CLICKED) {
      pxlMgSettings->video.scaleX++;
      HaltGui();
      scaleRightBtn.SetState(STATE_DEFAULT, -1);
      ResumeGui();
      updateVideo = 1;
    }
    // Need to reset video
    if(updateVideo) {
      HaltGui();
      ResetVideo_Menu(pxlMgSettings->video.offsetX,
                      pxlMgSettings->video.offsetY,
                      pxlMgSettings->video.scaleX,
                      pxlMgSettings->video.scaleY);
      snprintf(posValue, sizeof(posValue), "%i,%i", 
               pxlMgSettings->video.offsetX, pxlMgSettings->video.offsetY);
      snprintf(scaleValue, sizeof(scaleValue), "%i%%,%i%%", 
               pxlMgSettings->video.scaleX, pxlMgSettings->video.scaleY);
      posValueTxt.SetText(posValue);
      scaleValueTxt.SetText(scaleValue);
      updateVideo = 0;
      ResumeGui();
    }
  }

  HaltGui();
  mainWindow->Remove(subWindow);
  delete subWindow;

  return menu;
}

/****************************************************************************
 * MenuGame - Board view (actual game)
 ***************************************************************************/
static int MenuGame() {
  int menu = MENU_NONE;
  BoardView * boardView =
    new BoardView(gameDifficulty,
                  pxlMgSettings->board[gameDifficulty],
                  &pxlMgSettings->user);

  HaltGui();
  mainWindow->Append(boardView);
  ResumeGui();

  while(menu == MENU_NONE) {
    usleep(THREAD_SLEEP);
    menu = boardView->Run();
  }

  HaltGui();
  mainWindow->Remove(boardView);
  delete boardView;

  return menu;
}


/****************************************************************************
 * MainMenu
 ***************************************************************************/
void MainMenu(int menu)
{
  int currentMenu = menu;

#ifdef HW_RVL
  pointer[0] = new GuiImageData(player1_point_png);
  pointer[1] = new GuiImageData(player2_point_png);
  pointer[2] = new GuiImageData(player3_point_png);
  pointer[3] = new GuiImageData(player4_point_png);
#endif

  mainWindow = new GuiWindow(screenwidth, screenheight);

  bgImg = new GuiImage(screenwidth, screenheight, (GXColor){50, 50, 50, 255});
  bgImg->ColorStripe(30);

  mainWindow->Append(bgImg);

  ResumeGui();

  SplashScreen();
//   doneSplash = true;

  while(currentMenu != MENU_EXIT)
    {
      switch (currentMenu)
        {
        case MENU_START:
          currentMenu = MenuStart();
          break;
        case MENU_DIFF:
          currentMenu = MenuDiff();
          break;
        case MENU_SETTINGS:
          currentMenu = MenuSettings();
          break;
        case MENU_ADJUST_SCREEN:
          currentMenu = MenuAdjustScreen();
          break;
        case MENU_GAME:
          currentMenu = MenuGame();
          break;
        default: // unrecognized menu
          currentMenu = MenuStart();
          break;
        }
    }

  ResumeGui();
  ExitRequested = 1;
  while(1) usleep(THREAD_SLEEP);

  HaltGui();

  delete bgImg;
  delete mainWindow;
  delete pointer[0];
  delete pointer[1];
  delete pointer[2];
  delete pointer[3];

  mainWindow = NULL;
}

